package cn.rwklyd.BookKeeping.config;

import cn.rwklyd.BookKeeping.handler.AnonymousAuthenticationHandler;
import cn.rwklyd.BookKeeping.handler.CustomerAccessDeniedHandler;
import cn.rwklyd.BookKeeping.filter.JwtAuthenticationTokenFilter;
import cn.rwklyd.BookKeeping.handler.LoginFailureHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.cors.CorsConfigurationSource;



@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)  // 开启权限注解
@Slf4j
public class SecurityConfig {

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    @Autowired
    private CustomerAccessDeniedHandler customerAccessDeniedHandler;
    @Autowired
    private AnonymousAuthenticationHandler anonymousAuthenticationHandler;
    @Autowired
    private LoginFailureHandler loginFailureHandler;

    // 密码加密器
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 认证管理器
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager(); // 获取默认的认证管理器
    }

    // 放行接口
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http, LoginFailureHandler loginFailureHandler) throws Exception {
        // 配置关闭csrf,使用JWT了不需要
        http.csrf(csrf -> {
            csrf.disable();
            log.info("CSRF保护已禁用");
        });
        
        http.cors(cors -> {
            cors.configurationSource(corsConfigurationSource());
            log.info("CORS配置已启用");
        }); // 启用CORS

        // 不创建session会话
        http.sessionManagement(configurer -> {
            configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
            log.info("会话管理策略设置为STATELESS");
        });

        // 配置请求拦截方式
        String[] publicEndpoints = {
            "/system/login",
            "/system/register",
            "/system/sendEmailCode",
            "/token/refresh",
            "/token/logout",
            "/doc.html",
            "/swagger-ui/**",
            "/v3/api-docs/**",
            "/swagger-resources/**",
            "/webjars/**"
        };
        
        http.authorizeHttpRequests(auth -> {
            auth.requestMatchers(publicEndpoints).permitAll();
            auth.anyRequest().authenticated();
            log.info("已配置公共端点: {}", String.join(", ", publicEndpoints));
        });

        // 将token校验过滤器放进过滤器链中,放在最前面
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        log.info("JWT认证过滤器已添加到过滤器链");
        
        // 配置异常处理器
        http.exceptionHandling(configurer -> {
            configurer.accessDeniedHandler(customerAccessDeniedHandler);          // 权限不足处理器
            configurer.authenticationEntryPoint(anonymousAuthenticationHandler);  // 未登录处理器
            log.info("已配置异常处理器");
        });
        
        log.info("SecurityFilterChain配置完成");
        // 允许跨域
        return http.build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        log.info("配置CORS...");
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        configuration.addAllowedOriginPattern("*");  // 允许所有域名访问
        configuration.addAllowedHeader("*");  // 允许所有请求头
        configuration.addAllowedMethod("*");  // 允许所有请求方法
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();  // 创建CORS配置源
        source.registerCorsConfiguration("/**", configuration);  // 注册CORS配置
        log.info("CORS配置完成");
        return source;
    }
}
